package com.ccteam.fluidmusic.ui.album

import android.support.v4.media.MediaMetadataCompat
import androidx.lifecycle.*
import com.ccteam.fluidmusic.fluidmusic.common.MusicServiceConnectionFlow
import com.ccteam.fluidmusic.fluidmusic.common.utils.MediaIDHelper
import com.ccteam.fluidmusic.fluidmusic.media.extensions.id
import com.ccteam.fluidmusic.utils.cancelIfActive
import com.ccteam.fluidmusic.utils.setValueIfNew
import com.ccteam.fluidmusic.view.bean.ErrorMessage
import com.ccteam.fluidmusic.view.bean.LoadMessage
import com.ccteam.model.Resource
import com.ccteam.shared.core.UserCore
import com.ccteam.shared.domain.album.AlbumDetailUseCase
import com.ccteam.shared.domain.album.AlbumDetailUseCaseResult
import com.ccteam.shared.result.album.AlbumDetailHeaderItem
import com.ccteam.shared.result.album.AlbumDetailMusicItem
import com.ccteam.shared.utils.NO_PLAYING
import com.ccteam.shared.utils.PLAYING
import com.orhanobut.logger.Logger
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.flow.collectLatest
import kotlinx.coroutines.launch
import javax.inject.Inject

/**
 * @author Xiaoc
 * @since 2021/2/19
 *
 * 专辑详情界面对应的ViewModel
 */
@HiltViewModel
class AlbumDetailViewModel @Inject constructor(
    private val userCore: UserCore,
    private val mediaIDHelper: MediaIDHelper,
    private val musicServiceConnectionFlow: MusicServiceConnectionFlow,
    private val albumDetailUseCase: AlbumDetailUseCase,
    savedStateHandle: SavedStateHandle
): ViewModel() {

    /**
     * 网络请求专辑信息后存储的内容，用它来将 [loadMessage] 填充完整
     */
    private val albumDetailResult = MutableLiveData<Resource<AlbumDetailUseCaseResult>>(Resource.Loading(null))

    /**
     * 专辑详情头部内容
     */
    val albumHeader: LiveData<List<AlbumDetailHeaderItem>> = albumDetailResult.map {
        it.data?.albumHeader?.let { header ->
            listOf(header)
        } ?: emptyList()
    }

    /**
     * 专辑详情歌曲列表
     */
    private val _albumMusicList = MediatorLiveData<List<AlbumDetailMusicItem>>()
    val albumMusicList: LiveData<List<AlbumDetailMusicItem>> = _albumMusicList


    val parentId = MutableLiveData<String>()

    /**
     * 从savedStateHandle中获得对应albumId
     */
    val albumId = MutableLiveData<String>()

    val loadMessage: LiveData<LoadMessage> = albumDetailResult.map {

        when(it){
            is Resource.Success ->{
                if(it.data == null){
                    LoadMessage.Empty
                } else {
                    LoadMessage.NotLoading
                }
            }
            is Resource.Loading ->{
                LoadMessage.Loading
            }
            is Resource.Error ->{
                // 由于专辑内容会存放在内存中，如果data有数据则不会显示错误信息
                if(it.data != null){
                    LoadMessage.NotLoading
                } else {
                    LoadMessage.Error(ErrorMessage(it.message,it.errorCode))
                }
            }
        }
    }

    private val _shouldShowShareButton = MediatorLiveData<Boolean>()
    val shouldShowShareButton: LiveData<Boolean> get() = _shouldShowShareButton

    val isLogin = MutableLiveData<Boolean>()

    private var metadataChangedJob: Job? = null
    private var loginCheckJob: Job? = null
    init {

        // 监听albumId，当发生变化进行页面刷新
        _albumMusicList.addSource(albumId){
            parentId.value = mediaIDHelper.createMediaId(MediaIDHelper.ONLINE_MEDIA_ALBUM,it)
            refreshAlbumDetail()
        }

        albumId.setValueIfNew(savedStateHandle["albumId"])

        metadataChangedJob = viewModelScope.launch(Dispatchers.Default) {
            musicServiceConnectionFlow.nowPlaying.collectLatest {
                _albumMusicList.postValue(handleAlbumMusicMediaDataChanged(it))
            }
        }

        _shouldShowShareButton.addSource(isLogin){
            _shouldShowShareButton.value = it && !albumHeader.value.isNullOrEmpty()
        }
        _shouldShowShareButton.addSource(albumHeader){
            _shouldShowShareButton.value = !it.isNullOrEmpty() && isLogin.value == true
        }
        loginCheckJob = viewModelScope.launch {
            userCore.isLogin.collectLatest {
                isLogin.value = it
            }
        }
    }

    /**
     * 刷新专辑详情页信息
     */
    fun refreshAlbumDetail(){
        albumId.value?.let { albumId ->
            parentId.value?.let { parentId ->
                viewModelScope.launch {
                    albumDetailUseCase(Pair(parentId,albumId)).collectLatest {
                        albumDetailResult.value = it

                        _albumMusicList.value = it.data?.albumMusicList ?: emptyList()
                    }
                }
            }
        } ?: Logger.d("albumId为空:${albumId.value}")
    }

    /**
     * 当播放内容发生变化后，进行对应内容的更新，将正在播放项改变
     */
    private fun handleAlbumMusicMediaDataChanged(metadata: MediaMetadataCompat): List<AlbumDetailMusicItem>{
        return _albumMusicList.value?.map {
                val useResId = if (it.mediaId == metadata.id) PLAYING else NO_PLAYING
                it.copy(playbackRes = useResId)
        } ?: emptyList()
    }

    override fun onCleared() {
        super.onCleared()

        metadataChangedJob.cancelIfActive()
    }
}